package com.witsight.platform.config;


import java.text.SimpleDateFormat;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.witsight.platform.jackson.ObjectMapperCallBack;
import com.witsight.platform.util.lang.ClassUtil;
import com.witsight.platform.util.lang.DateUtil;
import com.witsight.platform.util.lang.MapUtil;
import com.witsight.platform.util.lang.MethodUtil;
import com.witsight.platform.util.tools.SpringUtil;

/**   
 * 说明：Json自动配置
 * @Title: JsonAutoConfig.java 
 * @Package com.witsight.platform.jackson 
 * @See: {@link #JsonAutoConfig()}
 * Copyright: Copyright (c) 2017
 * Company:sany huax witsight team by product
 * @author: penght  
 * @date: 2017年9月18日 下午4:45:42 
 * @version: V1.0
 *
 */
@Configuration
@EnableConfigurationProperties(PlaformCoreProperties.class)
@ConditionalOnClass(ObjectMapper.class)
@AutoConfigureAfter({ ComponentConfig.class })
public class JsonAutoConfig {
	/**
	 * 说明：定义后能再同一类中使用static常量log
	 */
	private static final Logger log = LoggerFactory.getLogger(JsonAutoConfig.class);
	@SuppressWarnings("unused")
	@Autowired
	private SpringUtil springUtil;
	/**
	 * 
	 * 说明：构建对象ObjectMapper
	 * @Title: objectMapper
	 * @See: {@link #objectMapper()}
	 * @author penght
	 * @return ObjectMapper
	 * @date: 2017年9月18日 下午5:08:01
	 */
	@Bean("objectMapper")
	@ConditionalOnMissingBean
	public ObjectMapper objectMapper(PlaformCoreProperties plaformCoreProperties) {
		if (log.isDebugEnabled()) {
			log.debug("config custom ObjectMapper.");
		}
		final ObjectMapper objectMapper = create(plaformCoreProperties);		
		Map<String, ObjectMapperCallBack> objectMapperCallBacks = SpringUtil.getBeansByType(ObjectMapperCallBack.class);
		if (MapUtil.isNotEmpty(objectMapperCallBacks)) {
			objectMapperCallBacks.forEach((name , callBack) -> {
				if (log.isDebugEnabled()) {
					log.debug("ObjectMapperCallBack name : {} configing.", name);
				}
				callBack.callBack(objectMapper);
			});
		}
		return objectMapper;
	}
	/**
	 * 
	 * 说明：创建简单的ObjectMapper
	 * @Title: create
	 * @See: {@link #create(PlaformCoreProperties)}
	 * @author penght
	 * @return 简单的ObjectMapper
	 * @date: 2017年9月18日 下午5:37:44
	 */
	public static ObjectMapper create() {
		return create(null);
	}
	
	private static ObjectMapper create(PlaformCoreProperties plaformCoreProperties) {
		ObjectMapper objectMapper = null;
		// 构建ObjectMapper
		Class<?> jackson2ObjectMapperBuilder = null;
		try {
			jackson2ObjectMapperBuilder = (Class<?>) ClassUtil.getClass(
					"org.springframework.http.converter.json.Jackson2ObjectMapperBuilder", true).newInstance();
			if (jackson2ObjectMapperBuilder != null) {
				objectMapper = (ObjectMapper) MethodUtil.invokeMethod(jackson2ObjectMapperBuilder.newInstance(), "build");
			}
		} catch (Exception e) {
			if (log.isWarnEnabled()) {
				log.warn("org.springframework.http.converter.json.Jackson2ObjectMapperBuilder parse error.");
			}
		}
		if (objectMapper == null) {
			objectMapper = new ObjectMapper();
		}
		/*
		 * 序列化设置
		 */
		// 允许单引号
		objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
		// 字段和值都加引号
		objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
		// 数字也加引号
		objectMapper.configure(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS, true);
		objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
		// 过滤提供者
		SimpleFilterProvider filter = new SimpleFilterProvider();
		filter.setFailOnUnknownId(false);
//		filter.addFilter(CustomAnnotationIntrospector.FILTER_BASE,
//		        SimpleBeanPropertyFilter.serializeAllExcept(FILTER_FILEDS));
		objectMapper.setFilterProvider(filter);
//		objectMapper.setAnnotationIntrospector(new CustomAnnotationIntrospector());
		objectMapper.setSerializationInclusion(Include.NON_NULL);
		/*
		 * 反序列化设置
		 */
		objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
		objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		objectMapper.configure(DeserializationFeature.WRAP_EXCEPTIONS, false);
		objectMapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);
		// objectMapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING,true);
		objectMapper.configure(Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);
		objectMapper.configure(Feature.ALLOW_NUMERIC_LEADING_ZEROS, true);
		objectMapper.configure(Feature.ALLOW_NON_NUMERIC_NUMBERS, true);
		// objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
//		 SimpleModule module = new SimpleModule();
//		 module.addSerializer(BoEntity.class, new BoEntityJsonSerializer());
//		 module.addDeserializer(BoEntity.class, new BoEntityJsonDeserializer());
//		 objectMapper.registerModule(module);
//		if (plaformCoreProperties != null) {
//			// 设置日期默认格式化
//			objectMapper.setDateFormat(new SimpleDateFormat(plaformCoreProperties.getDefaultDateFormat()));
//		} else {
//			// 设置日期默认格式化
//			objectMapper.setDateFormat(new SimpleDateFormat(DateUtil.DATETIME_TIME_ZONE_FORMAT));
//		}
		return objectMapper;
	}
}
